{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 使用预训练的 CNN"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "分成 2 步：\n",
    "\n",
    " 1. 特征提取\n",
    " \n",
    " 2. 微调模型\n",
    "\n",
    "\n",
    "<img src='imgs/预训练模型对比.jpg' width='300' height='200' align='left'/>\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "为什么仅复用卷积基而不用密集连接分类器？卷积基更具有通用性，而且密集连接分类器不包含了位置信息了（转换成了向量了已经）。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Using TensorFlow backend.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "WARNING:tensorflow:From /usr/local/lib/python3.7/site-packages/keras/backend/tensorflow_backend.py:63: The name tf.get_default_graph is deprecated. Please use tf.compat.v1.get_default_graph instead.\n",
      "\n",
      "WARNING:tensorflow:From /usr/local/lib/python3.7/site-packages/keras/backend/tensorflow_backend.py:488: The name tf.placeholder is deprecated. Please use tf.compat.v1.placeholder instead.\n",
      "\n",
      "WARNING:tensorflow:From /usr/local/lib/python3.7/site-packages/keras/backend/tensorflow_backend.py:3626: The name tf.random_uniform is deprecated. Please use tf.random.uniform instead.\n",
      "\n",
      "WARNING:tensorflow:From /usr/local/lib/python3.7/site-packages/keras/backend/tensorflow_backend.py:3454: The name tf.nn.max_pool is deprecated. Please use tf.nn.max_pool2d instead.\n",
      "\n",
      "Downloading data from https://github.com/fchollet/deep-learning-models/releases/download/v0.1/vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5\n",
      "58892288/58889256 [==============================] - 317s 5us/step\n",
      "WARNING:tensorflow:From /usr/local/lib/python3.7/site-packages/keras/backend/tensorflow_backend.py:158: The name tf.get_default_session is deprecated. Please use tf.compat.v1.get_default_session instead.\n",
      "\n",
      "WARNING:tensorflow:From /usr/local/lib/python3.7/site-packages/keras/backend/tensorflow_backend.py:163: The name tf.ConfigProto is deprecated. Please use tf.compat.v1.ConfigProto instead.\n",
      "\n",
      "WARNING:tensorflow:From /usr/local/lib/python3.7/site-packages/keras/backend/tensorflow_backend.py:168: The name tf.Session is deprecated. Please use tf.compat.v1.Session instead.\n",
      "\n",
      "WARNING:tensorflow:From /usr/local/lib/python3.7/site-packages/keras/backend/tensorflow_backend.py:172: The name tf.global_variables is deprecated. Please use tf.compat.v1.global_variables instead.\n",
      "\n",
      "WARNING:tensorflow:From /usr/local/lib/python3.7/site-packages/keras/backend/tensorflow_backend.py:180: The name tf.is_variable_initialized is deprecated. Please use tf.compat.v1.is_variable_initialized instead.\n",
      "\n",
      "WARNING:tensorflow:From /usr/local/lib/python3.7/site-packages/keras/backend/tensorflow_backend.py:187: The name tf.variables_initializer is deprecated. Please use tf.compat.v1.variables_initializer instead.\n",
      "\n"
     ]
    }
   ],
   "source": [
    "from keras.applications import VGG16\n",
    "\n",
    "# weights: 模型初始化的权重检查点\n",
    "# include_top: 是否包含分类器，自带的有1000个类别，我们只有2个类别，不需要他的\n",
    "conv_base = VGG16(weights='imagenet',\n",
    "                 include_top=False,\n",
    "                 input_shape=(150, 150, 3))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "_________________________________________________________________\n",
      "Layer (type)                 Output Shape              Param #   \n",
      "=================================================================\n",
      "input_1 (InputLayer)         (None, 150, 150, 3)       0         \n",
      "_________________________________________________________________\n",
      "block1_conv1 (Conv2D)        (None, 150, 150, 64)      1792      \n",
      "_________________________________________________________________\n",
      "block1_conv2 (Conv2D)        (None, 150, 150, 64)      36928     \n",
      "_________________________________________________________________\n",
      "block1_pool (MaxPooling2D)   (None, 75, 75, 64)        0         \n",
      "_________________________________________________________________\n",
      "block2_conv1 (Conv2D)        (None, 75, 75, 128)       73856     \n",
      "_________________________________________________________________\n",
      "block2_conv2 (Conv2D)        (None, 75, 75, 128)       147584    \n",
      "_________________________________________________________________\n",
      "block2_pool (MaxPooling2D)   (None, 37, 37, 128)       0         \n",
      "_________________________________________________________________\n",
      "block3_conv1 (Conv2D)        (None, 37, 37, 256)       295168    \n",
      "_________________________________________________________________\n",
      "block3_conv2 (Conv2D)        (None, 37, 37, 256)       590080    \n",
      "_________________________________________________________________\n",
      "block3_conv3 (Conv2D)        (None, 37, 37, 256)       590080    \n",
      "_________________________________________________________________\n",
      "block3_pool (MaxPooling2D)   (None, 18, 18, 256)       0         \n",
      "_________________________________________________________________\n",
      "block4_conv1 (Conv2D)        (None, 18, 18, 512)       1180160   \n",
      "_________________________________________________________________\n",
      "block4_conv2 (Conv2D)        (None, 18, 18, 512)       2359808   \n",
      "_________________________________________________________________\n",
      "block4_conv3 (Conv2D)        (None, 18, 18, 512)       2359808   \n",
      "_________________________________________________________________\n",
      "block4_pool (MaxPooling2D)   (None, 9, 9, 512)         0         \n",
      "_________________________________________________________________\n",
      "block5_conv1 (Conv2D)        (None, 9, 9, 512)         2359808   \n",
      "_________________________________________________________________\n",
      "block5_conv2 (Conv2D)        (None, 9, 9, 512)         2359808   \n",
      "_________________________________________________________________\n",
      "block5_conv3 (Conv2D)        (None, 9, 9, 512)         2359808   \n",
      "_________________________________________________________________\n",
      "block5_pool (MaxPooling2D)   (None, 4, 4, 512)         0         \n",
      "=================================================================\n",
      "Total params: 14,714,688\n",
      "Trainable params: 14,714,688\n",
      "Non-trainable params: 0\n",
      "_________________________________________________________________\n"
     ]
    }
   ],
   "source": [
    "conv_base.summary()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "导入了预训练模型后，需要增加最后的密集连接分类器。有2种方法：\n",
    "\n",
    " 1. 快速特征提取：在数据集上提前运行卷积基，输出结果序列化存储，后续直接创建新的线性分类器模型进行分类即可。\n",
    " \n",
    " 2. 使用数据增强的特征提取：在现有模型之上增加一些 Dense 层，**端对端**的运行整个模型。\n",
    " \n",
    "####  优缺点\n",
    "\n",
    "|方法|优点|缺点|\n",
    "|--|--|--|\n",
    "|快速特征提取|输入仅需要运行一次，代价低|不允许进行数据增强|\n",
    "|使用数据增强的特征提取|可使用数据增强，端对端|运行代价高|\n",
    "\n",
    "##### 1. 快速特征提取"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    " 1.1 提取出特征"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Found 2000 images belonging to 2 classes.\n",
      "Found 1000 images belonging to 2 classes.\n",
      "Found 1000 images belonging to 2 classes.\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "import numpy as np\n",
    "from keras.preprocessing.image import ImageDataGenerator\n",
    "\n",
    "base_dir = '/Users/haoxingxiao/academic/data/dogs-vs-cats/small'\n",
    "train_dir = os.path.join(base_dir, 'train')\n",
    "validation_dir = os.path.join(base_dir, 'validation')\n",
    "test_dir = os.path.join(base_dir, 'test')\n",
    "\n",
    "datagen = ImageDataGenerator(rescale=1./255)\n",
    "batch_size = 20\n",
    "\n",
    "def extract_features(directory, sample_count):\n",
    "    features = np.zeros(shape=(sample_count, 4, 4, 512))\n",
    "    labels = np.zeros(shape=(sample_count))\n",
    "    generator = datagen.flow_from_directory(\n",
    "        directory,\n",
    "        target_size=(150, 150),\n",
    "        batch_size=batch_size,\n",
    "        class_mode='binary'\n",
    "    )\n",
    "    i = 0\n",
    "    for inputs_batch, labels_batch in generator:\n",
    "        features_batch = conv_base.predict(inputs_batch)\n",
    "        features[i * batch_size:(i + 1) * batch_size] = features_batch\n",
    "        labels[i * batch_size:(i + 1) * batch_size] = labels_batch\n",
    "        i += 1\n",
    "        if i * batch_size >= sample_count:\n",
    "            break\n",
    "    return features, labels\n",
    "\n",
    "\n",
    "train_features, train_labels = extract_features(train_dir, 2000)\n",
    "validation_features, validation_labels = extract_features(validation_dir, 1000)\n",
    "test_features, test_lables = extract_features(test_dir, 1000)\n",
    "\n",
    "train_features = np.reshape(train_features, (2000, 4 * 4 * 512))\n",
    "validation_features = np.reshape(validation_features, (1000, 4 * 4 * 512))\n",
    "test_features = np.reshape(test_features, (1000, 4 * 4 * 512))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    " 1.2 实现自己的线性分类器"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "WARNING:tensorflow:From /usr/local/lib/python3.7/site-packages/keras/backend/tensorflow_backend.py:2990: calling dropout (from tensorflow.python.ops.nn_ops) with keep_prob is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please use `rate` instead of `keep_prob`. Rate should be set to `rate = 1 - keep_prob`.\n",
      "WARNING:tensorflow:From /usr/local/lib/python3.7/site-packages/keras/optimizers.py:711: The name tf.train.Optimizer is deprecated. Please use tf.compat.v1.train.Optimizer instead.\n",
      "\n",
      "WARNING:tensorflow:From /usr/local/lib/python3.7/site-packages/keras/backend/tensorflow_backend.py:2921: The name tf.log is deprecated. Please use tf.math.log instead.\n",
      "\n",
      "WARNING:tensorflow:From /usr/local/lib/python3.7/site-packages/tensorflow_core/python/ops/nn_impl.py:183: where (from tensorflow.python.ops.array_ops) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Use tf.where in 2.0, which has the same broadcast rule as np.where\n",
      "WARNING:tensorflow:From /usr/local/lib/python3.7/site-packages/keras/backend/tensorflow_backend.py:671: calling Constant.__init__ (from tensorflow.python.ops.init_ops) with dtype is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Call initializer instance with the dtype argument instead of passing it to the constructor\n",
      "WARNING:tensorflow:From /usr/local/lib/python3.7/site-packages/keras/backend/tensorflow_backend.py:949: The name tf.assign_add is deprecated. Please use tf.compat.v1.assign_add instead.\n",
      "\n",
      "WARNING:tensorflow:From /usr/local/lib/python3.7/site-packages/keras/backend/tensorflow_backend.py:936: The name tf.assign is deprecated. Please use tf.compat.v1.assign instead.\n",
      "\n",
      "Train on 2000 samples, validate on 1000 samples\n",
      "Epoch 1/30\n",
      "2000/2000 [==============================] - 2s 1ms/step - loss: 0.6029 - acc: 0.6715 - val_loss: 0.4470 - val_acc: 0.8370\n",
      "Epoch 2/30\n",
      "2000/2000 [==============================] - 2s 1ms/step - loss: 0.4389 - acc: 0.8000 - val_loss: 0.3735 - val_acc: 0.8550\n",
      "Epoch 3/30\n",
      "2000/2000 [==============================] - 2s 1ms/step - loss: 0.3661 - acc: 0.8405 - val_loss: 0.3248 - val_acc: 0.8820\n",
      "Epoch 4/30\n",
      "2000/2000 [==============================] - 2s 1ms/step - loss: 0.3288 - acc: 0.8620 - val_loss: 0.3070 - val_acc: 0.8750\n",
      "Epoch 5/30\n",
      "2000/2000 [==============================] - 2s 1ms/step - loss: 0.2898 - acc: 0.8835 - val_loss: 0.2831 - val_acc: 0.8950\n",
      "Epoch 6/30\n",
      "2000/2000 [==============================] - 2s 1ms/step - loss: 0.2819 - acc: 0.8870 - val_loss: 0.2794 - val_acc: 0.8860\n",
      "Epoch 7/30\n",
      "2000/2000 [==============================] - 2s 1ms/step - loss: 0.2551 - acc: 0.8975 - val_loss: 0.2637 - val_acc: 0.8910\n",
      "Epoch 8/30\n",
      "2000/2000 [==============================] - 2s 1ms/step - loss: 0.2381 - acc: 0.9130 - val_loss: 0.2653 - val_acc: 0.8910\n",
      "Epoch 9/30\n",
      "2000/2000 [==============================] - 2s 1ms/step - loss: 0.2252 - acc: 0.9105 - val_loss: 0.2590 - val_acc: 0.8960\n",
      "Epoch 10/30\n",
      "2000/2000 [==============================] - 2s 1ms/step - loss: 0.2142 - acc: 0.9300 - val_loss: 0.2457 - val_acc: 0.9020\n",
      "Epoch 11/30\n",
      "2000/2000 [==============================] - 2s 1ms/step - loss: 0.2015 - acc: 0.9240 - val_loss: 0.2476 - val_acc: 0.8970\n",
      "Epoch 12/30\n",
      "2000/2000 [==============================] - 2s 1ms/step - loss: 0.1929 - acc: 0.9305 - val_loss: 0.2409 - val_acc: 0.9020\n",
      "Epoch 13/30\n",
      "2000/2000 [==============================] - 2s 1ms/step - loss: 0.1929 - acc: 0.9295 - val_loss: 0.2422 - val_acc: 0.8990\n",
      "Epoch 14/30\n",
      "2000/2000 [==============================] - 2s 1ms/step - loss: 0.1817 - acc: 0.9335 - val_loss: 0.2376 - val_acc: 0.8990\n",
      "Epoch 15/30\n",
      "2000/2000 [==============================] - 2s 1ms/step - loss: 0.1683 - acc: 0.9425 - val_loss: 0.2338 - val_acc: 0.9020\n",
      "Epoch 16/30\n",
      "2000/2000 [==============================] - 2s 1ms/step - loss: 0.1626 - acc: 0.9390 - val_loss: 0.2332 - val_acc: 0.9050\n",
      "Epoch 17/30\n",
      "2000/2000 [==============================] - 2s 1ms/step - loss: 0.1570 - acc: 0.9460 - val_loss: 0.2398 - val_acc: 0.8960\n",
      "Epoch 18/30\n",
      "2000/2000 [==============================] - 2s 1ms/step - loss: 0.1498 - acc: 0.9480 - val_loss: 0.2322 - val_acc: 0.9060\n",
      "Epoch 19/30\n",
      "2000/2000 [==============================] - 2s 1ms/step - loss: 0.1454 - acc: 0.9490 - val_loss: 0.2301 - val_acc: 0.9030\n",
      "Epoch 20/30\n",
      "2000/2000 [==============================] - 2s 1ms/step - loss: 0.1440 - acc: 0.9480 - val_loss: 0.2320 - val_acc: 0.8970\n",
      "Epoch 21/30\n",
      "2000/2000 [==============================] - 2s 1ms/step - loss: 0.1301 - acc: 0.9590 - val_loss: 0.2295 - val_acc: 0.9090\n",
      "Epoch 22/30\n",
      "2000/2000 [==============================] - 2s 1ms/step - loss: 0.1293 - acc: 0.9590 - val_loss: 0.2305 - val_acc: 0.9020\n",
      "Epoch 23/30\n",
      "2000/2000 [==============================] - 2s 1ms/step - loss: 0.1225 - acc: 0.9565 - val_loss: 0.2297 - val_acc: 0.9090\n",
      "Epoch 24/30\n",
      "2000/2000 [==============================] - 2s 999us/step - loss: 0.1178 - acc: 0.9585 - val_loss: 0.2325 - val_acc: 0.8970\n",
      "Epoch 25/30\n",
      "2000/2000 [==============================] - 2s 1ms/step - loss: 0.1120 - acc: 0.9660 - val_loss: 0.2397 - val_acc: 0.8980\n",
      "Epoch 26/30\n",
      "2000/2000 [==============================] - 2s 1ms/step - loss: 0.1168 - acc: 0.9650 - val_loss: 0.2332 - val_acc: 0.8970\n",
      "Epoch 27/30\n",
      "2000/2000 [==============================] - 2s 998us/step - loss: 0.1081 - acc: 0.9625 - val_loss: 0.2322 - val_acc: 0.8960\n",
      "Epoch 28/30\n",
      "2000/2000 [==============================] - 2s 992us/step - loss: 0.1023 - acc: 0.9670 - val_loss: 0.2494 - val_acc: 0.8930\n",
      "Epoch 29/30\n",
      "2000/2000 [==============================] - 2s 993us/step - loss: 0.0985 - acc: 0.9665 - val_loss: 0.2277 - val_acc: 0.9070\n",
      "Epoch 30/30\n",
      "2000/2000 [==============================] - 2s 989us/step - loss: 0.0951 - acc: 0.9750 - val_loss: 0.2321 - val_acc: 0.8990\n"
     ]
    }
   ],
   "source": [
    "from keras import models\n",
    "from keras import layers\n",
    "from keras import optimizers\n",
    "\n",
    "model = models.Sequential()\n",
    "model.add(layers.Dense(256, activation='relu', input_dim=4*4*512))\n",
    "model.add(layers.Dropout(0.5))\n",
    "model.add(layers.Dense(1, activation='sigmoid'))\n",
    "\n",
    "model.compile(optimizer=optimizers.RMSprop(lr=2e-5),\n",
    "             loss='binary_crossentropy',\n",
    "             metrics=['acc'])\n",
    "history = model.fit(train_features, \n",
    "                    train_labels, \n",
    "                    epochs=30, \n",
    "                    batch_size=20, \n",
    "                    validation_data=(validation_features, validation_labels))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "看看 loss 和 accuracy："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXQAAAEICAYAAABPgw/pAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy8li6FKAAAgAElEQVR4nO3deZwU1bn/8c8DAiOL7IqCMihGGRYBR1wQAUMU4xUuSgwIokkM6o0xifEm/ESNIZdEvcYQDVcliVscxV0xaoiJKC6JsgSRJQgq4AAioCA4CAw8vz9ODfQM3TPdQ8/0dM/3/XrVq7urqque6pp5+vQ5p06ZuyMiItmvQaYDEBGR9FBCFxHJEUroIiI5QgldRCRHKKGLiOQIJXQRkRyhhJ6jzKyhmW0zs6PSuW4mmVlXM6uRfrYVt21mfzWzMTURh5ndYGZ3V/f9IokoodcRUUItm/aY2faY13ETS2Xcfbe7N3f31elct64ys7+Z2Y1x5l9gZmvMrGEq23P3s9y9KA1xDTGzlRW2/Qt3v+JAt13FPt3MflxT+5C6SQm9jogSanN3bw6sBs6LmbdfYjGzg2o/yjrtAeDiOPMvBh5y9921HE8mXQJ8Coyr7R3r7zKzlNCzhJn9j5k9amaPmNlWYKyZnWpm/zSzzWa2zszuMLNG0foHRaW0/Oj1Q9HyF81sq5n9w8y6pLputPwcM3vPzLaY2Z1m9oaZXZog7mRivNzMVpjZZ2Z2R8x7G5rZb8xsk5l9AAyt5CN6CuhgZqfFvL8t8HXgwej1MDNbYGafm9lqM7uhks/79bJjqioOM7vMzJZGn9X7ZnZZNL8l8BxwVMyvrUOjc3l/zPtHmNni6DN62cyOi1lWbGbXmNm70ef9iJk1qSTuFsD5wH8BBWbWu8LyM6LzscXMPjKzi6P5TaNjXB0tm21mTeL9wohiGhQ9T+nvMnpPz+gX1adm9rGZ/cTMOppZiZm1ilmvX7RcXxLJcndNdWwCVgJDKsz7H2AncB7hi/hg4CTgZOAg4GjgPeCqaP2DAAfyo9cPARuBQqAR8Cih5JrquocCW4Hh0bJrgF3ApQmOJZkYnwVaAvmEkuWQaPlVwGKgE9AWmB3+ZBN+bvcBd8e8/h4wN+b1mUD36PM7ITrG/4iWdY3dNvB62TFVFUd0To4GLNrHdqBXtGwIsDLOubw/et4N2Ba9rxFwHbAMaBQtLwb+CXSI9v0ecFkln8G3ovc0AF4EfhOzrEu0rwujz74d0Dtadg/wd+BwoCFwehRPvPiLgUHV/LtsCawHfgA0AQ4B+kXL/gp8N2Y/d8bGrymJ3JHpADTFOSmJE/rLVbzvWuDx6Hm8JB2b7IYBi6qx7reB12KWGbCOBAk9yRhPiVn+FHBt9Hx2bPIilLa9km0PInwhNIlevwV8v5L1fwf8b/S8soSeahx/Br4XPa8qof8ceDhmWQPgY+D06HUxMCpm+e3A7yrZ9yvAbdHzi6PkeVD0+oayz77CexoCO4DucZYlk9BT+bu8GJiTYL0xwKsxfxsbgL7p/v/K5UlVLtnlo9gXZna8mT0f/Sz9HJhEKHUl8nHM8xKgeTXWPSI2Dg//fcWJNpJkjEntC1hVSbwArwKfA+eZ2VeAPsAjMbGcamavmNkGM9sCXBYnlngqjcPM/sPM3oqqEDYDZyW53bJt792eu+8hfJ4dY9ZJ6rxFVWZnAGVtLk9H65ZVER0JvB/nrYcBjRMsS0Yqf5eJYiiL9wQLva2GAp+4+/xqxlQvKaFnl4pd5e4BFgFd3f0Q4EZCibkmrSNUPQBgZkb55FPRgcS4jpAAylTarTL6cnmQ0Bh4MfCCu2+MWWU68CRwpLu3BP6QZCwJ4zCzg4EngF8Bh7l7K0LVQdl2q+reuBboHLO9BoTPd00ScVU0Ltrvi2b2MbCCkKgviZZ/BBwT533rCdUm8ZZ9ATSNie8gQtVPrFT+LhPFgLuXEM7PGML5+1O89SQxJfTs1gLYAnxhZt2Ay2thn38G+prZedE/9w+A9jUU42PAD6MGs7bAT5N4z4OE0t23CT1fKsbyqbt/aWanAKPSEEcTQtLcAOw2s/8AvhqzfD3QLmqsTLTtYWY2KGo4/G9CG8VbScYWaxwhefaOmb5J+MXSmlCVNtRCV86DzKydmZ3goQfQ/cAUM+sQNQL3j+L5N9DCzM6OXv+MULdemcrO+QxCI/FVUaPrIWbWL2b5g4Rzd24Ur6RACT27/ZhQ+tpKKBU9WtM7dPf1hCRxO7CJUNr6F6EONt0x3kVoqHsXmEMoCVcV3wrgbUKifb7C4iuBX0W9Ma4jJNMDisPdNwM/IlQXfAqMJHzplS1fRCh1rox6fRxaId7FhM/nLsKXwlBgmLvvSjI2AMzsdEL1zVR3/7hsiuJaCXzT3T8kNF7+NIp1PtAz2sSPgKXAvGjZLwFz98+A7xO+HNdEy2KrgOJJeM7dfQvwNeACwpfde8DAmPfOJtSfv+XuCavyJD6LGiBEqsXCBTtrgZHu/lqm45HsZ2azgXvd/f5Mx5JtVEKXlJnZUDNrFfWHvoHQbfHtDIclOSCqCusBPJ7pWLKRErpUx+nAB4QqgrOBEe6eqMpFJClmVgT8BfiBu3+R6XiykapcRERyhEroIiI5ImNjJLRr187z8/MztXsRkaw0b968je4et6twxhJ6fn4+c+fOzdTuRUSykpklvGJaVS4iIjlCCV1EJEcooYuI5AgNHC9ST+zatYvi4mK+/PLLTIciScjLy6NTp040alTV0Dn7KKGL1BPFxcW0aNGC/Px8wiCZUle5O5s2baK4uJguXbpU/YZIVlW5FBVBfj40aBAeiw74Fr4i9ceXX35J27ZtlcyzgJnRtm3blH9NJZXQo7E7llm47+OEBOtcaGZLonsjPpxSFEkoKoLx42HVKnAPj+PHK6mLpELJPHtU51xVmdCj0fSmAucABcBoMyuosM6xwP8D+rt7d+CHKUdShYkToaSk/LySkjBfRESSK6H3A1a4+wfuvpNw15fhFdb5LmEc5s8A3P2T9IYJq1enNl9E6pZNmzbRu3dvevfuTYcOHejYsePe1zt37kxqG9/61rdYtmxZpetMnTqVojT9dD/99NNZsGBBWrZVG5JpFO1I+XsGFhPu6B3rKwBm9gbhhrM3uftfKm7IzMYD4wGOOqrSu4nt56ijQjVLvPkikn5FReEX8OrV4f9s8mQYM6b622vbtu3e5HjTTTfRvHlzrr322nLr7L3ZcYP4Zc377ruvyv1873vfq36QWS5djaIHAccS7ro+Gvi9mbWquJK7T3P3QncvbN++sruW7W/yZGjatPy8pk3DfBFJr9pss1qxYgUFBQWMGTOG7t27s27dOsaPH09hYSHdu3dn0qRJe9ctKzGXlpbSqlUrJkyYwAknnMCpp57KJ5+EioHrr7+eKVOm7F1/woQJ9OvXj+OOO44333wTgC+++IILLriAgoICRo4cSWFhYZUl8YceeoiePXvSo0cPrrvuOgBKS0u5+OKL986/4447APjNb35DQUEBvXr1YuzYsWn/zBJJpoS+hvI3yI13A9tiwi2jdgEfmtl7hAQ/Jy1Rsq9kkM4Sg4jEV1mbVU38z/373//mwQcfpLCwEICbb76ZNm3aUFpayuDBgxk5ciQFBeWa7tiyZQsDBw7k5ptv5pprruHee+9lwoT9+2y4O2+//TYzZsxg0qRJ/OUvf+HOO++kQ4cOPPnkk7zzzjv07du30viKi4u5/vrrmTt3Li1btmTIkCH8+c9/pn379mzcuJF3330XgM2bNwNw6623smrVKho3brx3Xm1IpoQ+BzjWzLqYWWPCjXVnVFjnGULpHDNrR6iC+SCNcQLhD2nlStizJzwqmYvUjNpuszrmmGP2JnOARx55hL59+9K3b1+WLl3KkiVL9nvPwQcfzDnnnAPAiSeeyMqVK+Nu+/zzz99vnddff51Ro8I9wk844QS6d+9eaXxvvfUWZ555Ju3ataNRo0ZcdNFFzJ49m65du7Js2TKuvvpqZs6cScuWLQHo3r07Y8eOpaioKKULgw5UlQnd3UuBq4CZhJvIPubui81skpkNi1abCWwysyXALOC/3X1TTQUtIjUrUdtUTbVZNWvWbO/z5cuX89vf/paXX36ZhQsXMnTo0Lj9sRs3brz3ecOGDSktLY277SZNmlS5TnW1bduWhQsXMmDAAKZOncrll18OwMyZM7niiiuYM2cO/fr1Y/fu3WndbyJJ1aG7+wvu/hV3P8bdJ0fzbnT3GdFzd/dr3L3A3Xu6+/SaDFpEalYm26w+//xzWrRowSGHHMK6deuYOXNm2vfRv39/HnvsMQDefffduL8AYp188snMmjWLTZs2UVpayvTp0xk4cCAbNmzA3fnGN77BpEmTmD9/Prt376a4uJgzzzyTW2+9lY0bN1JSsf6qhujSfxHZTybbrPr27UtBQQHHH388nTt3pn///mnfx/e//33GjRtHQUHB3qmsuiSeTp068Ytf/IJBgwbh7px33nmce+65zJ8/n+985zu4O2bGLbfcQmlpKRdddBFbt25lz549XHvttbRo0SLtxxBPxu4pWlhY6LrBhUjtWbp0Kd26dct0GHVCaWkppaWl5OXlsXz5cs466yyWL1/OQQfVrTJuvHNmZvPcvTDe+nUrehGRWrBt2za++tWvUlpairtzzz331LlkXh3ZfwQiIilq1aoV8+bNy3QYaZdVoy2KiEhiSugiIjlCCV1EJEcooYuI5AgldBGpFYMHD97vIqEpU6Zw5ZVXVvq+5s2bA7B27VpGjhwZd51BgwZRVTfoKVOmlLvA5+tf/3paxlm56aabuO222w54O+mghC4itWL06NFMn17+IvLp06czevTopN5/xBFH8MQTT1R7/xUT+gsvvECrVvsNCpvVlNBFpFaMHDmS559/fu/NLFauXMnatWsZMGDA3n7hffv2pWfPnjz77LP7vX/lypX06NEDgO3btzNq1Ci6devGiBEj2L59+971rrzyyr1D7/7sZz8D4I477mDt2rUMHjyYwYMHA5Cfn8/GjRsBuP322+nRowc9evTYO/TuypUr6datG9/97nfp3r07Z511Vrn9xLNgwQJOOeUUevXqxYgRI/jss8/27r9sON2yQcFeffXVvTf46NOnD1u3bq32Z1tG/dBF6qEf/hDSfSOe3r0hyoVxtWnThn79+vHiiy8yfPhwpk+fzoUXXoiZkZeXx9NPP80hhxzCxo0bOeWUUxg2bFjC+2reddddNG3alKVLl7Jw4cJyw99OnjyZNm3asHv3br761a+ycOFCrr76am6//XZmzZpFu3btym1r3rx53Hfffbz11lu4OyeffDIDBw6kdevWLF++nEceeYTf//73XHjhhTz55JOVjm8+btw47rzzTgYOHMiNN97Iz3/+c6ZMmcLNN9/Mhx9+SJMmTfZW89x2221MnTqV/v37s23bNvLy8lL4tONTCV1Eak1stUtsdYu7c91119GrVy+GDBnCmjVrWL9+fcLtzJ49e29i7dWrF7169dq77LHHHqNv37706dOHxYsXVznw1uuvv86IESNo1qwZzZs35/zzz+e1114DoEuXLvTu3RuofIheCOOzb968mYEDBwJwySWXMHv27L0xjhkzhoceemjvFan9+/fnmmuu4Y477mDz5s1puVJVJXSReqiyknRNGj58OD/60Y+YP38+JSUlnHjiiQAUFRWxYcMG5s2bR6NGjcjPz487ZG5VPvzwQ2677TbmzJlD69atufTSS6u1nTJlQ+9CGH63qiqXRJ5//nlmz57Nc889x+TJk3n33XeZMGEC5557Li+88AL9+/dn5syZHH/88dWOFVRCF5Fa1Lx5cwYPHsy3v/3tco2hW7Zs4dBDD6VRo0bMmjWLVfFuIBzjjDPO4OGHHwZg0aJFLFy4EAhD7zZr1oyWLVuyfv16Xnzxxb3vadGiRdx66gEDBvDMM89QUlLCF198wdNP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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "acc = history.history['acc']\n",
    "val_acc = history.history['val_acc']\n",
    "loss = history.history['loss']\n",
    "val_loss = history.history['val_loss']\n",
    "\n",
    "epochs = range(1, len(acc) + 1)\n",
    "\n",
    "plt.plot(epochs, acc, 'bo', label='Training Acc')\n",
    "plt.plot(epochs, val_acc, 'b', label='Validation Acc')\n",
    "plt.title('Training and Validation Accuracy')\n",
    "plt.legend()\n",
    "\n",
    "plt.figure()\n",
    "\n",
    "plt.plot(epochs, loss, 'bo', label='Training loss')\n",
    "plt.plot(epochs, val_loss, 'b', label='Validation loss')\n",
    "plt.title('Training and Validation Accuracy')\n",
    "plt.legend()\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "精确度达到了90%。比之前效果好很多。但是一开始就开始过拟合。\n",
    "**使用数据增强对小数据集的过拟合非常重要。**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 2. 端对端\n",
    "\n",
    "**警告：该方法只能在 GPU 上运行**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "WARNING:tensorflow:From /usr/local/lib/python3.7/site-packages/keras/backend/tensorflow_backend.py:1255: calling reduce_prod_v1 (from tensorflow.python.ops.math_ops) with keep_dims is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "keep_dims is deprecated, use keepdims instead\n",
      "_________________________________________________________________\n",
      "Layer (type)                 Output Shape              Param #   \n",
      "=================================================================\n",
      "vgg16 (Model)                (None, 4, 4, 512)         14714688  \n",
      "_________________________________________________________________\n",
      "flatten_1 (Flatten)          (None, 8192)              0         \n",
      "_________________________________________________________________\n",
      "dense_3 (Dense)              (None, 256)               2097408   \n",
      "_________________________________________________________________\n",
      "dense_4 (Dense)              (None, 1)                 257       \n",
      "=================================================================\n",
      "Total params: 16,812,353\n",
      "Trainable params: 16,812,353\n",
      "Non-trainable params: 0\n",
      "_________________________________________________________________\n"
     ]
    }
   ],
   "source": [
    "from keras import models\n",
    "from keras import layers\n",
    "\n",
    "model = models.Sequential()\n",
    "model.add(conv_base)\n",
    "model.add(layers.Flatten())\n",
    "model.add(layers.Dense(256, activation='relu'))\n",
    "model.add(layers.Dense(1, activation='sigmoid'))\n",
    "\n",
    "model.summary()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "需要先冻结卷积基："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "before freeze: 30\n",
      "after freeze: 4\n"
     ]
    }
   ],
   "source": [
    "print('before freeze:', len(model.trainable_weights))\n",
    "conv_base.trainable = False\n",
    "print('after freeze:', len(model.trainable_weights))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "冻结之后，只有Dense层的权重才会被训练。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Found 2000 images belonging to 2 classes.\n",
      "Found 1000 images belonging to 2 classes.\n",
      "Epoch 1/30\n",
      "100/100 [==============================] - 364s 4s/step - loss: 0.5015 - acc: 0.7470 - val_loss: 0.2051 - val_acc: 0.9060\n",
      "Epoch 2/30\n",
      "100/100 [==============================] - 366s 4s/step - loss: 0.3286 - acc: 0.8540 - val_loss: 0.2573 - val_acc: 0.8830\n",
      "Epoch 3/30\n",
      "100/100 [==============================] - 388s 4s/step - loss: 0.2578 - acc: 0.8980 - val_loss: 0.1335 - val_acc: 0.9450\n",
      "Epoch 4/30\n",
      "100/100 [==============================] - 387s 4s/step - loss: 0.2466 - acc: 0.8985 - val_loss: 0.2798 - val_acc: 0.8800\n",
      "Epoch 5/30\n",
      "100/100 [==============================] - 389s 4s/step - loss: 0.1903 - acc: 0.9180 - val_loss: 0.1164 - val_acc: 0.9500\n",
      "Epoch 6/30\n",
      "100/100 [==============================] - 390s 4s/step - loss: 0.1942 - acc: 0.9245 - val_loss: 0.1320 - val_acc: 0.9330\n",
      "Epoch 7/30\n",
      "100/100 [==============================] - 393s 4s/step - loss: 0.1864 - acc: 0.9205 - val_loss: 0.1111 - val_acc: 0.9480\n",
      "Epoch 8/30\n",
      "100/100 [==============================] - 421s 4s/step - loss: 0.1731 - acc: 0.9350 - val_loss: 0.3237 - val_acc: 0.8890\n",
      "Epoch 9/30\n",
      "100/100 [==============================] - 400s 4s/step - loss: 0.1481 - acc: 0.9415 - val_loss: 0.1137 - val_acc: 0.9450\n",
      "Epoch 10/30\n",
      "100/100 [==============================] - 405s 4s/step - loss: 0.1513 - acc: 0.9365 - val_loss: 0.1257 - val_acc: 0.9520\n",
      "Epoch 11/30\n",
      "100/100 [==============================] - 415s 4s/step - loss: 0.1444 - acc: 0.9480 - val_loss: 0.1160 - val_acc: 0.9560\n",
      "Epoch 12/30\n",
      "100/100 [==============================] - 387s 4s/step - loss: 0.1437 - acc: 0.9460 - val_loss: 0.1274 - val_acc: 0.9450\n",
      "Epoch 13/30\n",
      "100/100 [==============================] - 378s 4s/step - loss: 0.1254 - acc: 0.9490 - val_loss: 0.1548 - val_acc: 0.9560\n",
      "Epoch 14/30\n",
      "100/100 [==============================] - 369s 4s/step - loss: 0.1265 - acc: 0.9490 - val_loss: 0.1578 - val_acc: 0.9400\n",
      "Epoch 15/30\n",
      "100/100 [==============================] - 375s 4s/step - loss: 0.1410 - acc: 0.9465 - val_loss: 0.1165 - val_acc: 0.9570\n",
      "Epoch 16/30\n",
      "100/100 [==============================] - 360s 4s/step - loss: 0.1217 - acc: 0.9485 - val_loss: 0.1407 - val_acc: 0.9580\n",
      "Epoch 17/30\n",
      "100/100 [==============================] - 358s 4s/step - loss: 0.1194 - acc: 0.9555 - val_loss: 0.4188 - val_acc: 0.9020\n",
      "Epoch 18/30\n",
      "100/100 [==============================] - 357s 4s/step - loss: 0.1251 - acc: 0.9555 - val_loss: 0.1465 - val_acc: 0.9470\n",
      "Epoch 19/30\n",
      "100/100 [==============================] - 352s 4s/step - loss: 0.1281 - acc: 0.9480 - val_loss: 0.2303 - val_acc: 0.9480\n",
      "Epoch 20/30\n",
      "100/100 [==============================] - 361s 4s/step - loss: 0.1176 - acc: 0.9560 - val_loss: 0.1681 - val_acc: 0.9470\n",
      "Epoch 21/30\n",
      "100/100 [==============================] - 354s 4s/step - loss: 0.1199 - acc: 0.9550 - val_loss: 0.1210 - val_acc: 0.9600\n",
      "Epoch 22/30\n",
      "100/100 [==============================] - 357s 4s/step - loss: 0.1162 - acc: 0.9640 - val_loss: 0.1696 - val_acc: 0.9580\n",
      "Epoch 23/30\n",
      "100/100 [==============================] - 356s 4s/step - loss: 0.1346 - acc: 0.9545 - val_loss: 0.1219 - val_acc: 0.9610\n",
      "Epoch 24/30\n",
      "100/100 [==============================] - 351s 4s/step - loss: 0.1195 - acc: 0.9630 - val_loss: 0.1311 - val_acc: 0.9580\n",
      "Epoch 25/30\n",
      "100/100 [==============================] - 359s 4s/step - loss: 0.1339 - acc: 0.9490 - val_loss: 0.1397 - val_acc: 0.9500\n",
      "Epoch 26/30\n",
      "100/100 [==============================] - 358s 4s/step - loss: 0.1072 - acc: 0.9605 - val_loss: 0.1488 - val_acc: 0.9570\n",
      "Epoch 27/30\n",
      "100/100 [==============================] - 353s 4s/step - loss: 0.1327 - acc: 0.9590 - val_loss: 0.1351 - val_acc: 0.9570\n",
      "Epoch 28/30\n",
      "100/100 [==============================] - 353s 4s/step - loss: 0.1212 - acc: 0.9590 - val_loss: 0.1208 - val_acc: 0.9650\n",
      "Epoch 29/30\n",
      "100/100 [==============================] - 358s 4s/step - loss: 0.1404 - acc: 0.9510 - val_loss: 0.1134 - val_acc: 0.9610\n",
      "Epoch 30/30\n",
      "100/100 [==============================] - 358s 4s/step - loss: 0.1168 - acc: 0.9600 - val_loss: 0.1064 - val_acc: 0.9600\n"
     ]
    }
   ],
   "source": [
    "from keras.preprocessing.image import ImageDataGenerator\n",
    "from keras import optimizers\n",
    "\n",
    "train_datagen = ImageDataGenerator(\n",
    "    rescale=1./255,\n",
    "    rotation_range=40,\n",
    "    width_shift_range=0.2,\n",
    "    height_shift_range=0.2,\n",
    "    shear_range=0.2,\n",
    "    zoom_range=0.2,\n",
    "    horizontal_flip=True,\n",
    "    fill_mode='nearest'\n",
    ")\n",
    "\n",
    "test_datagen = ImageDataGenerator(rescale=1./255)\n",
    "\n",
    "train_generator = train_datagen.flow_from_directory(\n",
    "    train_dir,\n",
    "    target_size=(150, 150),\n",
    "    batch_size=20,\n",
    "    class_mode='binary'\n",
    ")\n",
    "\n",
    "validation_generator = test_datagen.flow_from_directory(\n",
    "    validation_dir,\n",
    "    target_size=(150, 150),\n",
    "    batch_size=20,\n",
    "    class_mode='binary'\n",
    ")\n",
    "\n",
    "model.compile(\n",
    "    loss='binary_crossentropy',\n",
    "    optimizer=optimizers.RMSprop(lr=2e-5),\n",
    "    metrics=['acc']\n",
    ")\n",
    "\n",
    "history = model.fit_generator(\n",
    "    train_generator,\n",
    "    steps_per_epoch=100,\n",
    "    epochs=30,\n",
    "    validation_data=validation_generator,\n",
    "    validation_steps=50\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在 CPU 上硬跑完了~看看效果吧："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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Tg5XX301y5cvZ/bs2Vx55ZWAG4L55ptvZuvWrTRs2JC//vWv9OrVi0ceeYTp06fToEEDxowZw+TJkytsMxGVBnoRaQhMBc4DioFcEXlLVY8M/qCqPw9b/nbglLBN7FPVQUmV0hgTeO3atWPo0KG88847jB07lpkzZ3LZZZchIjRr1ow33niDo48+mm+//ZbTTjuNiy66KOb9U5966ilatGjB8uXLWbx4MZmZmUfmTZo0iXbt2nH48GHOOeccFi9ezB133MFjjz3GvHnz6NChQ7ltLVq0iOeff56FCxeiqpx66qmMGDGCtm3bsmrVKnJycnjmmWe47LLLeO2117jqqqsqlOfVV1/lvffeY8WKFTzxxBNHAn12djZ33303F198Mfv376e0tJR33nmH2bNns3DhQlq0aHFknJxk+KnRDwVWq+oaABGZCYwFKo7y41wB3J90yYwxNSZezTudQumbUKD/y1/+ArgBwO655x7mz59PgwYN2LBhA1u2bKFz585RtzN//nzuuOMOgCM3+QiZNWsW06ZNo6SkhE2bNlFYWFhufqSPPvqIiy+++MgImpdccgkLFizgoosuomfPngwa5OqxsYZCDv0q6NatG126dOGGG25g+/btNG7cmA0bNhwZL6dZs2aAG8r4+uuvp0WLFkDZEMfJ8JOj7wKsD3tf7E2rQES6Az2BuWGTm4lInoh8KiI/ibHeBG+ZvK1bt/osenmpvn+lMab6jR07ljlz5vD555+zd+9eBg8eDMCMGTPYunUrixYtIj8/n06dOkUdmrgyX3/9NY8++ihz5sxh8eLF/OhHP6rSdkJCQxxD7GGOc3JyWLFiBT169KBXr17s3LmT1157rcr7rIpUN8aOB/6mqofDpnX3Btq5EpgiIr0iV1LVaaqapapZHTt2THinoftXrl0Lqu55wgQL9sbUNS1btmTUqFHccMMN5Rphd+zYwTHHHEPjxo3LDf8by1lnncUrr7wCwNKlS1m8eDHghjg+6qijaN26NVu2bOGdd945sk6rVq3YtWtXhW0NHz6cN998k71797Jnzx7eeOMNhg8f7ut4SktLmTVrFkuWLDkylPHs2bPJycmhVatWdO3a9cjtBA8cOMDevXs577zzeP755480DKcideMn0G8Ajgt739WbFs14ICd8gqpu8J7XAB9QPn+fEtV5/0pjTHpdccUVFBQUlAv02dnZ5OXlMWDAAF566SV69+4ddxu33HILu3fvpk+fPvz6178+8stg4MCBnHLKKfTu3Zsrr7yy3BDHEyZMYPTo0YwaNarctjIzM7nuuusYOnQop556KjfeeCOnnOIvjC1YsIAuXbpw7LHHHpl21llnUVhYyKZNm3j55Zd5/PHHycjI4IwzzmDz5s2MHj2aiy66iKysLAYNGsSjjz7qa1/xVDpMsYg0Ar4EzsEF+FzgSlVdFrFcb+CfQE/1NioibYG9qnpARDoAnwBjwxtyI1VlmOIGDVxNvmLZ3VjZxpjK2TDFdUeiwxRXWqNX1RLgNuBdYDkwS1WXichDIhLeVXI8MFPLnzn6AHkiUgDMAybHC/JVVd33rzTGmLrEVz96VX0beDti2q8j3j8QZb2PgQFJlM+X6r5/pTHG1CWBuDK2Ju9faUyQ1LY7zpmKqvIdBebGI9nZFtiNSUazZs3Ytm0b7du3j3khkqlZqsq2bduO9Ln3KzCB3hiTnK5du1JcXExVr2Ux1aNZs2Z07do1oXUs0BtjAGjcuDE9e/as6WKYNAhEjt4YY0xsFuiNMSbgLNAbY0zAVXplbHUTka1A5EAWHYBva6A46RS0Ywra8UDwjiloxwPBO6Zkjqe7qkYdLKzWBfpoRCQv1qW9dVXQjiloxwPBO6agHQ8E75jSdTyWujHGmICzQG+MMQFXVwL9tJouQBoE7ZiCdjwQvGMK2vFA8I4pLcdTJ3L0xhhjqq6u1OiNMcZUkQV6Y4wJuFof6EVktIisFJHVInJ3TZcnWSJSJCJLRCRfRBK7lVYtISLPicg3IrI0bFo7EXlPRFZ5z21rsoyJiHE8D4jIBu97yheRC2qyjIkSkeNEZJ6IFIrIMhH5mTe9Tn5PcY6nzn5PItJMRD4TkQLvmB70pvcUkYVezHtVRJokva/anKMXkYa42xieBxTjbmN4RTruUlVdRKQIyFLVOnuRh4icBewGXlLV/t60/wdsV9XJ3gm5rar+qibL6VeM43kA2K2qyd+wswaIyA+AH6jq5yLSClgE/AS4jjr4PcU5nsuoo9+TuLGgj1LV3SLSGPgI+BnwC+B1VZ0pIn8GClT1qWT2Vdtr9EOB1aq6RlUPAjOBsTVcpnpPVecDkbemHwu86L1+EfdPWCfEOJ46TVU3qern3utduNuAdqGOfk9xjqfOUme397ax91DgbOBv3vSUfEe1PdB3AdaHvS+mjn+5uC/yXyKySEQm1HRhUqiTqm7yXm8GOtVkYVLkNhFZ7KV26kSKIxoR6QGcAiwkAN9TxPFAHf6eRKShiOQD3wDvAV8B33v36oYUxbzaHuiDaJiqZgJjgFu9tEGgeDeIr705QX+eAnoBg4BNwB9qtjhVIyItgdeAO1V1Z/i8uvg9RTmeOv09qephVR0EdMVlMHqnYz+1PdBvAI4Le9/Vm1ZnqeoG7/kb4A3clxsEW7w8aiif+k0NlycpqrrF+ycsBZ6hDn5PXt73NWCGqr7uTa6z31O04wnC9wSgqt8D84DTgTYiEropVEpiXm0P9LnAiV4rdBNgPPBWDZepykTkKK8hCRE5CjgfWBp/rTrjLeBa7/W1wOwaLEvSQsHQczF17HvyGvr+AixX1cfCZtXJ7ynW8dTl70lEOopIG+91c1ynk+W4gD/OWywl31Gt7nUD4HWXmgI0BJ5T1Uk1XKQqE5HjcbV4cLdxfKUuHo+I5AAjcUOqbgHuB94EZgHdcMNMX6aqdaKBM8bxjMSlAxQoAm4Ky23XeiIyDFgALAFKvcn34PLade57inM8V1BHvycRycA1tjbEVbpnqepDXpyYCbQDvgCuUtUDSe2rtgd6Y4wxyantqRtjjDFJskBvjDEBZ4HeGGMCzgK9McYEnAV6Y4wJOAv0xhgTcBbojTEm4P4/Wr0y4bjX7RYAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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WFWrIuYdfxI4PuixYTBmDEybBj17goh7njYtPS/DMIwDyXZ/2IcffshNN93E8uXL6datG/fffz8LFizg/fff5/XXX2f58uUHHLN161aGDBnC+++/z0knncRTTz0Vs21V5d133+Whhx7a+6fx2GOP0blzZ5YvX86dd97Je++9l9C+8vJy7rjjDubOnct7773Hv/71L1555RUWLlzIpk2bWLp0KR988AGXX345AA8++CCLFy9myZIlPP7442l+OsEJIvTzgSNFpFhEmuIWTp4VWUFEukRsDsetMQkwBzhLRNp5nbBneWWhM2YMrFkDtbXu2UTeMMIn2/1hvXv3prS0dO/2s88+y6BBgxg0aBArVqyIKfQHHXQQ55xzDgDHH388a9asidn2t7/97QPqvPXWW1x8sVsb/rjjjqOkpCShfe+88w7f/OY36dixI02aNOGSSy5h3rx5HHHEEaxcuZIbbriBOXPmcPDBBwNQUlLCpZdeyvTp05Ma8JQudQq9qlYD43ECvQKYqarLRGSiiAz3qt0gIstE5H3gBuAK79jNwL24P4v5wESvzDCMeki8fq9M9Ye1bNly7+tVq1bxy1/+kjfeeIMlS5YwbNiwmPnkTZs23fu6qKiI6urqmG03a9aszjqp0qFDB5YsWcKpp57KlClT+P73vw/AnDlzuPbaa5k/fz6DBw+mpqYm1PeNR6AYvarOVtWjVLW3qk7yyu5S1Vne61tVtURVj1PVoar6YcSxT6nqEd6j7h4TwzDyllz2h3355Ze0bt2aNm3aUFFRwZw54QcHTj75ZGbOnAnA0qVLY94xRHLCCScwd+5cqqqqqK6uZsaMGQwZMoTKykpUle985ztMnDiRRYsWUVNTQ3l5Od/85jd58MEH2bRpEzuj42AZwqZAMAwjMH5INMysm6AMGjSIvn37cswxx9CzZ09OPvnk0N/jBz/4AZdffjl9+/bd+/DDLrHo3r079957L6effjqqygUXXMB5553HokWLuPrqq1FVRIQHHniA6upqLrnkErZt20ZtbS233HILrVu3Dv0cYpF3a8aWlpaqLTxiGNljxYoV9OnTJ9dm5AXV1dVUV1fTvHlzVq1axVlnncWqVato3Di/fOJY10xEFqpqaaz6+WW9YRhGDtm+fTtnnHEG1dXVqCpTp07NO5FPhfp/BoZhGCHRtm1bFi5cmGszQqdg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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "acc = history.history['acc']\n",
    "val_acc = history.history['val_acc']\n",
    "loss = history.history['loss']\n",
    "val_loss = history.history['val_loss']\n",
    "\n",
    "epochs = range(1, len(acc) + 1)\n",
    "\n",
    "plt.plot(epochs, acc, 'bo', label='Training Acc')\n",
    "plt.plot(epochs, val_acc, 'b', label='Validation Acc')\n",
    "plt.title('Training and Validation Accuracy')\n",
    "plt.legend()\n",
    "\n",
    "plt.figure()\n",
    "\n",
    "plt.plot(epochs, loss, 'bo', label='Training loss')\n",
    "plt.plot(epochs, val_loss, 'b', label='Validation loss')\n",
    "plt.title('Training and Validation Accuracy')\n",
    "plt.legend()\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Wow，很快训练和验证集上都稳定在95%左右，效果不错！"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 微调模型\n",
    "\n",
    "相对于特征提取，这里将原始模型的最顶部几层解冻，调整其参数。仅调整了一些最抽象的表示。\n",
    "\n",
    "**步骤**：\n",
    "\n",
    " 1. 已经训练好的模型上添加自定义网络\n",
    " \n",
    " 2. 冻结基模型\n",
    " \n",
    " 3. 训练添加的模型\n",
    " \n",
    " 4. 解冻基网络中几层\n",
    " \n",
    " 5. 联合训练解冻层和添加的网络\n",
    " \n",
    "将模型修改为只训练最后一层："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "_________________________________________________________________\n",
      "Layer (type)                 Output Shape              Param #   \n",
      "=================================================================\n",
      "input_1 (InputLayer)         (None, 150, 150, 3)       0         \n",
      "_________________________________________________________________\n",
      "block1_conv1 (Conv2D)        (None, 150, 150, 64)      1792      \n",
      "_________________________________________________________________\n",
      "block1_conv2 (Conv2D)        (None, 150, 150, 64)      36928     \n",
      "_________________________________________________________________\n",
      "block1_pool (MaxPooling2D)   (None, 75, 75, 64)        0         \n",
      "_________________________________________________________________\n",
      "block2_conv1 (Conv2D)        (None, 75, 75, 128)       73856     \n",
      "_________________________________________________________________\n",
      "block2_conv2 (Conv2D)        (None, 75, 75, 128)       147584    \n",
      "_________________________________________________________________\n",
      "block2_pool (MaxPooling2D)   (None, 37, 37, 128)       0         \n",
      "_________________________________________________________________\n",
      "block3_conv1 (Conv2D)        (None, 37, 37, 256)       295168    \n",
      "_________________________________________________________________\n",
      "block3_conv2 (Conv2D)        (None, 37, 37, 256)       590080    \n",
      "_________________________________________________________________\n",
      "block3_conv3 (Conv2D)        (None, 37, 37, 256)       590080    \n",
      "_________________________________________________________________\n",
      "block3_pool (MaxPooling2D)   (None, 18, 18, 256)       0         \n",
      "_________________________________________________________________\n",
      "block4_conv1 (Conv2D)        (None, 18, 18, 512)       1180160   \n",
      "_________________________________________________________________\n",
      "block4_conv2 (Conv2D)        (None, 18, 18, 512)       2359808   \n",
      "_________________________________________________________________\n",
      "block4_conv3 (Conv2D)        (None, 18, 18, 512)       2359808   \n",
      "_________________________________________________________________\n",
      "block4_pool (MaxPooling2D)   (None, 9, 9, 512)         0         \n",
      "_________________________________________________________________\n",
      "block5_conv1 (Conv2D)        (None, 9, 9, 512)         2359808   \n",
      "_________________________________________________________________\n",
      "block5_conv2 (Conv2D)        (None, 9, 9, 512)         2359808   \n",
      "_________________________________________________________________\n",
      "block5_conv3 (Conv2D)        (None, 9, 9, 512)         2359808   \n",
      "_________________________________________________________________\n",
      "block5_pool (MaxPooling2D)   (None, 4, 4, 512)         0         \n",
      "=================================================================\n",
      "Total params: 14,714,688\n",
      "Trainable params: 7,079,424\n",
      "Non-trainable params: 7,635,264\n",
      "_________________________________________________________________\n"
     ]
    }
   ],
   "source": [
    "conv_base.trainable = True\n",
    "set_trainable = False\n",
    "for layer in conv_base.layers:\n",
    "    if layer.name == 'block5_conv1':\n",
    "        set_trainable = True\n",
    "    if set_trainable:\n",
    "        layer.trainable = True\n",
    "    else:\n",
    "        layer.trainable = False\n",
    "conv_base.summary()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/100\n",
      "100/100 [==============================] - 147s 1s/step - loss: 0.0447 - acc: 0.9865 - val_loss: 0.1476 - val_acc: 0.9610\n",
      "Epoch 2/100\n",
      "100/100 [==============================] - 152s 2s/step - loss: 0.0306 - acc: 0.9895 - val_loss: 0.1614 - val_acc: 0.9650\n",
      "Epoch 3/100\n",
      "100/100 [==============================] - 172s 2s/step - loss: 0.0320 - acc: 0.9910 - val_loss: 0.1702 - val_acc: 0.9620\n",
      "Epoch 4/100\n",
      "100/100 [==============================] - 181s 2s/step - loss: 0.0463 - acc: 0.9870 - val_loss: 0.1488 - val_acc: 0.9600\n",
      "Epoch 5/100\n",
      "100/100 [==============================] - 182s 2s/step - loss: 0.0381 - acc: 0.9875 - val_loss: 0.1771 - val_acc: 0.9600\n",
      "Epoch 6/100\n",
      "100/100 [==============================] - 184s 2s/step - loss: 0.0547 - acc: 0.9860 - val_loss: 0.1423 - val_acc: 0.9660\n",
      "Epoch 7/100\n",
      "100/100 [==============================] - 180s 2s/step - loss: 0.0361 - acc: 0.9900 - val_loss: 0.1490 - val_acc: 0.9740\n",
      "Epoch 8/100\n",
      "100/100 [==============================] - 174s 2s/step - loss: 0.0314 - acc: 0.9880 - val_loss: 0.1314 - val_acc: 0.9690\n",
      "Epoch 9/100\n",
      "100/100 [==============================] - 176s 2s/step - loss: 0.0274 - acc: 0.9905 - val_loss: 0.1433 - val_acc: 0.9700\n",
      "Epoch 10/100\n",
      "100/100 [==============================] - 178s 2s/step - loss: 0.0269 - acc: 0.9915 - val_loss: 0.1603 - val_acc: 0.9700\n",
      "Epoch 11/100\n",
      "100/100 [==============================] - 179s 2s/step - loss: 0.0437 - acc: 0.9875 - val_loss: 0.1529 - val_acc: 0.9660\n",
      "Epoch 12/100\n",
      "100/100 [==============================] - 183s 2s/step - loss: 0.0243 - acc: 0.9945 - val_loss: 0.1603 - val_acc: 0.9670\n",
      "Epoch 13/100\n",
      "100/100 [==============================] - 182s 2s/step - loss: 0.0446 - acc: 0.9900 - val_loss: 0.1369 - val_acc: 0.9690\n",
      "Epoch 14/100\n",
      "100/100 [==============================] - 196s 2s/step - loss: 0.0245 - acc: 0.9905 - val_loss: 0.1181 - val_acc: 0.9750\n",
      "Epoch 15/100\n",
      "100/100 [==============================] - 191s 2s/step - loss: 0.0240 - acc: 0.9925 - val_loss: 0.1302 - val_acc: 0.9700\n",
      "Epoch 16/100\n",
      "100/100 [==============================] - 193s 2s/step - loss: 0.0222 - acc: 0.9925 - val_loss: 0.1766 - val_acc: 0.9720\n",
      "Epoch 17/100\n",
      "100/100 [==============================] - 182s 2s/step - loss: 0.0329 - acc: 0.9885 - val_loss: 0.1281 - val_acc: 0.9740\n",
      "Epoch 18/100\n",
      "100/100 [==============================] - 175s 2s/step - loss: 0.0303 - acc: 0.9900 - val_loss: 0.1472 - val_acc: 0.9720\n",
      "Epoch 19/100\n",
      "100/100 [==============================] - 171s 2s/step - loss: 0.0298 - acc: 0.9895 - val_loss: 0.1600 - val_acc: 0.9620\n",
      "Epoch 20/100\n",
      "100/100 [==============================] - 171s 2s/step - loss: 0.0241 - acc: 0.9900 - val_loss: 0.1580 - val_acc: 0.9690\n",
      "Epoch 21/100\n",
      "100/100 [==============================] - 173s 2s/step - loss: 0.0263 - acc: 0.9905 - val_loss: 0.2168 - val_acc: 0.9620\n",
      "Epoch 22/100\n",
      "100/100 [==============================] - 175s 2s/step - loss: 0.0368 - acc: 0.9865 - val_loss: 0.1897 - val_acc: 0.9670\n",
      "Epoch 23/100\n",
      "100/100 [==============================] - 179s 2s/step - loss: 0.0135 - acc: 0.9960 - val_loss: 0.1869 - val_acc: 0.9670\n",
      "Epoch 24/100\n",
      "100/100 [==============================] - 175s 2s/step - loss: 0.0366 - acc: 0.9900 - val_loss: 0.2061 - val_acc: 0.9710\n",
      "Epoch 25/100\n",
      "100/100 [==============================] - 168s 2s/step - loss: 0.0338 - acc: 0.9920 - val_loss: 0.2200 - val_acc: 0.9670\n",
      "Epoch 26/100\n",
      "100/100 [==============================] - 164s 2s/step - loss: 0.0209 - acc: 0.9940 - val_loss: 0.1346 - val_acc: 0.9730\n",
      "Epoch 27/100\n",
      "100/100 [==============================] - 158s 2s/step - loss: 0.0140 - acc: 0.9950 - val_loss: 0.1976 - val_acc: 0.9700\n",
      "Epoch 28/100\n",
      "100/100 [==============================] - 155s 2s/step - loss: 0.0334 - acc: 0.9955 - val_loss: 0.2404 - val_acc: 0.9610\n",
      "Epoch 29/100\n",
      "100/100 [==============================] - 158s 2s/step - loss: 0.0278 - acc: 0.9905 - val_loss: 0.2301 - val_acc: 0.9680\n",
      "Epoch 30/100\n",
      "100/100 [==============================] - 156s 2s/step - loss: 0.0235 - acc: 0.9940 - val_loss: 0.2319 - val_acc: 0.9680\n",
      "Epoch 31/100\n",
      "100/100 [==============================] - 158s 2s/step - loss: 0.0263 - acc: 0.9905 - val_loss: 0.1447 - val_acc: 0.9760\n",
      "Epoch 32/100\n",
      "100/100 [==============================] - 157s 2s/step - loss: 0.0245 - acc: 0.9930 - val_loss: 0.2602 - val_acc: 0.9640\n",
      "Epoch 33/100\n",
      "100/100 [==============================] - 156s 2s/step - loss: 0.0229 - acc: 0.9940 - val_loss: 0.1607 - val_acc: 0.9710\n",
      "Epoch 34/100\n",
      "100/100 [==============================] - 153s 2s/step - loss: 0.0105 - acc: 0.9955 - val_loss: 0.2017 - val_acc: 0.9690\n",
      "Epoch 35/100\n",
      "100/100 [==============================] - 153s 2s/step - loss: 0.0369 - acc: 0.9930 - val_loss: 0.1594 - val_acc: 0.9740\n",
      "Epoch 36/100\n",
      "100/100 [==============================] - 154s 2s/step - loss: 0.0192 - acc: 0.9935 - val_loss: 0.1617 - val_acc: 0.9740\n",
      "Epoch 37/100\n",
      "100/100 [==============================] - 156s 2s/step - loss: 0.0258 - acc: 0.9945 - val_loss: 0.2069 - val_acc: 0.9660\n",
      "Epoch 38/100\n",
      "100/100 [==============================] - 157s 2s/step - loss: 0.0215 - acc: 0.9955 - val_loss: 0.1507 - val_acc: 0.9750\n",
      "Epoch 39/100\n",
      "100/100 [==============================] - 157s 2s/step - loss: 0.0381 - acc: 0.9925 - val_loss: 0.1250 - val_acc: 0.9800\n",
      "Epoch 40/100\n",
      "100/100 [==============================] - 154s 2s/step - loss: 0.0206 - acc: 0.9955 - val_loss: 0.1641 - val_acc: 0.9740\n",
      "Epoch 41/100\n",
      "100/100 [==============================] - 153s 2s/step - loss: 0.0314 - acc: 0.9925 - val_loss: 0.2026 - val_acc: 0.9700\n",
      "Epoch 42/100\n",
      "100/100 [==============================] - 153s 2s/step - loss: 0.0132 - acc: 0.9955 - val_loss: 0.1678 - val_acc: 0.9740\n",
      "Epoch 43/100\n",
      "100/100 [==============================] - 154s 2s/step - loss: 0.0402 - acc: 0.9895 - val_loss: 0.1277 - val_acc: 0.9750\n",
      "Epoch 44/100\n",
      "100/100 [==============================] - 155s 2s/step - loss: 0.0230 - acc: 0.9920 - val_loss: 0.1889 - val_acc: 0.9660\n",
      "Epoch 45/100\n",
      "100/100 [==============================] - 157s 2s/step - loss: 0.0197 - acc: 0.9935 - val_loss: 0.1897 - val_acc: 0.9740\n",
      "Epoch 46/100\n",
      "100/100 [==============================] - 161s 2s/step - loss: 0.0186 - acc: 0.9955 - val_loss: 0.1581 - val_acc: 0.9720\n",
      "Epoch 47/100\n",
      "100/100 [==============================] - 156s 2s/step - loss: 0.0315 - acc: 0.9925 - val_loss: 0.1727 - val_acc: 0.9740\n",
      "Epoch 48/100\n",
      "100/100 [==============================] - 156s 2s/step - loss: 0.0263 - acc: 0.9940 - val_loss: 0.2310 - val_acc: 0.9640\n",
      "Epoch 49/100\n",
      "100/100 [==============================] - 162s 2s/step - loss: 0.0439 - acc: 0.9935 - val_loss: 0.2206 - val_acc: 0.9650\n",
      "Epoch 50/100\n",
      "100/100 [==============================] - 165s 2s/step - loss: 0.0506 - acc: 0.9910 - val_loss: 0.1970 - val_acc: 0.9660\n",
      "Epoch 51/100\n",
      "100/100 [==============================] - 152s 2s/step - loss: 0.0112 - acc: 0.9960 - val_loss: 0.1928 - val_acc: 0.9740\n",
      "Epoch 52/100\n",
      "100/100 [==============================] - 5151s 52s/step - loss: 0.0224 - acc: 0.9920 - val_loss: 0.1695 - val_acc: 0.9710\n",
      "Epoch 53/100\n",
      "100/100 [==============================] - 1977s 20s/step - loss: 0.0367 - acc: 0.9910 - val_loss: 0.1910 - val_acc: 0.9640\n",
      "Epoch 54/100\n",
      "100/100 [==============================] - 318s 3s/step - loss: 0.0120 - acc: 0.9960 - val_loss: 0.1869 - val_acc: 0.9730\n",
      "Epoch 55/100\n",
      "100/100 [==============================] - 141s 1s/step - loss: 0.0306 - acc: 0.9925 - val_loss: 0.1554 - val_acc: 0.9730\n",
      "Epoch 56/100\n",
      "100/100 [==============================] - 747s 7s/step - loss: 0.0273 - acc: 0.9955 - val_loss: 0.1862 - val_acc: 0.9700\n",
      "Epoch 57/100\n",
      "100/100 [==============================] - 139s 1s/step - loss: 0.0216 - acc: 0.9930 - val_loss: 0.1814 - val_acc: 0.9720\n",
      "Epoch 58/100\n",
      "100/100 [==============================] - 139s 1s/step - loss: 0.0262 - acc: 0.9915 - val_loss: 0.2652 - val_acc: 0.9630\n",
      "Epoch 59/100\n",
      "100/100 [==============================] - 142s 1s/step - loss: 0.0197 - acc: 0.9940 - val_loss: 0.2311 - val_acc: 0.9690\n",
      "Epoch 60/100\n",
      "100/100 [==============================] - 143s 1s/step - loss: 0.0178 - acc: 0.9950 - val_loss: 0.2295 - val_acc: 0.9680\n",
      "Epoch 61/100\n",
      "100/100 [==============================] - 146s 1s/step - loss: 0.0153 - acc: 0.9955 - val_loss: 0.2107 - val_acc: 0.9700\n",
      "Epoch 62/100\n",
      "100/100 [==============================] - 147s 1s/step - loss: 0.0233 - acc: 0.9945 - val_loss: 0.2406 - val_acc: 0.9710\n",
      "Epoch 63/100\n",
      "100/100 [==============================] - 143s 1s/step - loss: 0.0173 - acc: 0.9930 - val_loss: 0.3085 - val_acc: 0.9540\n",
      "Epoch 64/100\n",
      "100/100 [==============================] - 143s 1s/step - loss: 0.0293 - acc: 0.9930 - val_loss: 0.2230 - val_acc: 0.9710\n",
      "Epoch 65/100\n",
      "100/100 [==============================] - 143s 1s/step - loss: 0.0090 - acc: 0.9985 - val_loss: 0.1956 - val_acc: 0.9710\n",
      "Epoch 66/100\n",
      "100/100 [==============================] - 144s 1s/step - loss: 0.0201 - acc: 0.9955 - val_loss: 0.2445 - val_acc: 0.9670\n",
      "Epoch 67/100\n",
      "100/100 [==============================] - 144s 1s/step - loss: 0.0283 - acc: 0.9940 - val_loss: 0.2278 - val_acc: 0.9690\n",
      "Epoch 68/100\n",
      "100/100 [==============================] - 144s 1s/step - loss: 0.0146 - acc: 0.9955 - val_loss: 0.1708 - val_acc: 0.9740\n",
      "Epoch 69/100\n",
      "100/100 [==============================] - 148s 1s/step - loss: 0.0247 - acc: 0.9950 - val_loss: 0.1607 - val_acc: 0.9750\n",
      "Epoch 70/100\n",
      "100/100 [==============================] - 144s 1s/step - loss: 0.0211 - acc: 0.9940 - val_loss: 0.1464 - val_acc: 0.9750\n",
      "Epoch 71/100\n",
      "100/100 [==============================] - 145s 1s/step - loss: 0.0213 - acc: 0.9930 - val_loss: 0.1917 - val_acc: 0.9680\n",
      "Epoch 72/100\n",
      "100/100 [==============================] - 146s 1s/step - loss: 0.0153 - acc: 0.9945 - val_loss: 0.2073 - val_acc: 0.9730\n",
      "Epoch 73/100\n",
      "100/100 [==============================] - 146s 1s/step - loss: 0.0273 - acc: 0.9945 - val_loss: 0.3133 - val_acc: 0.9640\n",
      "Epoch 74/100\n",
      "100/100 [==============================] - 146s 1s/step - loss: 0.0389 - acc: 0.9910 - val_loss: 0.1690 - val_acc: 0.9700\n",
      "Epoch 75/100\n",
      "100/100 [==============================] - 146s 1s/step - loss: 0.0164 - acc: 0.9960 - val_loss: 0.2486 - val_acc: 0.9630\n",
      "Epoch 76/100\n",
      "100/100 [==============================] - 1722s 17s/step - loss: 0.0126 - acc: 0.9965 - val_loss: 0.2828 - val_acc: 0.9680\n",
      "Epoch 77/100\n",
      "100/100 [==============================] - 6244s 62s/step - loss: 0.0290 - acc: 0.9960 - val_loss: 0.3509 - val_acc: 0.9590\n",
      "Epoch 78/100\n",
      "100/100 [==============================] - 5276s 53s/step - loss: 0.0160 - acc: 0.9970 - val_loss: 0.2673 - val_acc: 0.9700\n",
      "Epoch 79/100\n",
      "100/100 [==============================] - 145s 1s/step - loss: 0.0377 - acc: 0.9945 - val_loss: 0.2752 - val_acc: 0.9620\n",
      "Epoch 80/100\n",
      "100/100 [==============================] - 151s 2s/step - loss: 0.0459 - acc: 0.9920 - val_loss: 0.2086 - val_acc: 0.9690\n",
      "Epoch 81/100\n",
      "100/100 [==============================] - 196s 2s/step - loss: 0.0254 - acc: 0.9935 - val_loss: 0.2149 - val_acc: 0.9730\n",
      "Epoch 82/100\n",
      "100/100 [==============================] - 173s 2s/step - loss: 0.0238 - acc: 0.9955 - val_loss: 0.2299 - val_acc: 0.9690\n",
      "Epoch 83/100\n",
      "100/100 [==============================] - 210s 2s/step - loss: 0.0187 - acc: 0.9940 - val_loss: 0.1894 - val_acc: 0.9720\n",
      "Epoch 84/100\n",
      "100/100 [==============================] - 194s 2s/step - loss: 0.0284 - acc: 0.9960 - val_loss: 0.1649 - val_acc: 0.9750\n",
      "Epoch 85/100\n",
      "100/100 [==============================] - 187s 2s/step - loss: 0.0345 - acc: 0.9920 - val_loss: 0.1938 - val_acc: 0.9740\n",
      "Epoch 86/100\n",
      "100/100 [==============================] - 160s 2s/step - loss: 0.0350 - acc: 0.9915 - val_loss: 0.1973 - val_acc: 0.9670\n",
      "Epoch 87/100\n",
      "100/100 [==============================] - 145s 1s/step - loss: 0.0191 - acc: 0.9950 - val_loss: 0.1775 - val_acc: 0.9720\n",
      "Epoch 88/100\n",
      "100/100 [==============================] - 146s 1s/step - loss: 0.0359 - acc: 0.9950 - val_loss: 0.2816 - val_acc: 0.9590\n",
      "Epoch 89/100\n",
      "100/100 [==============================] - 149s 1s/step - loss: 0.0139 - acc: 0.9940 - val_loss: 0.2132 - val_acc: 0.9710\n",
      "Epoch 90/100\n",
      "100/100 [==============================] - 155s 2s/step - loss: 0.0273 - acc: 0.9950 - val_loss: 0.2122 - val_acc: 0.9680\n",
      "Epoch 91/100\n",
      "100/100 [==============================] - 146s 1s/step - loss: 0.0294 - acc: 0.9940 - val_loss: 0.2296 - val_acc: 0.9700\n",
      "Epoch 92/100\n",
      "100/100 [==============================] - 148s 1s/step - loss: 0.0246 - acc: 0.9935 - val_loss: 0.2235 - val_acc: 0.9680\n",
      "Epoch 93/100\n",
      "100/100 [==============================] - 145s 1s/step - loss: 0.0142 - acc: 0.9955 - val_loss: 0.2219 - val_acc: 0.9690\n",
      "Epoch 94/100\n",
      "100/100 [==============================] - 145s 1s/step - loss: 0.0250 - acc: 0.9925 - val_loss: 0.2273 - val_acc: 0.9650\n",
      "Epoch 95/100\n",
      "100/100 [==============================] - 146s 1s/step - loss: 0.0197 - acc: 0.9950 - val_loss: 0.2481 - val_acc: 0.9670\n",
      "Epoch 96/100\n",
      "100/100 [==============================] - 141s 1s/step - loss: 0.0274 - acc: 0.9945 - val_loss: 0.1852 - val_acc: 0.9700\n",
      "Epoch 97/100\n",
      "100/100 [==============================] - 142s 1s/step - loss: 0.0211 - acc: 0.9955 - val_loss: 0.2172 - val_acc: 0.9650\n",
      "Epoch 98/100\n",
      "100/100 [==============================] - 143s 1s/step - loss: 0.0214 - acc: 0.9935 - val_loss: 0.1842 - val_acc: 0.9720\n",
      "Epoch 99/100\n",
      "100/100 [==============================] - 141s 1s/step - loss: 0.0170 - acc: 0.9965 - val_loss: 0.2334 - val_acc: 0.9730\n",
      "Epoch 100/100\n",
      "100/100 [==============================] - 141s 1s/step - loss: 0.0327 - acc: 0.9900 - val_loss: 0.1959 - val_acc: 0.9700\n"
     ]
    }
   ],
   "source": [
    "model.compile(loss='binary_crossentropy',\n",
    "             optimizer=optimizers.RMSprop(lr=1e-5),\n",
    "             metrics=['acc'])\n",
    "history = model.fit_generator(\n",
    "    train_generator,\n",
    "    steps_per_epoch=100,\n",
    "    epochs=100,\n",
    "    validation_data=validation_generator,\n",
    "    validation_steps=50\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "绘图："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'history' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-6-a23dd6aa517e>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0macc\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mhistory\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mhistory\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'acc'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      2\u001b[0m \u001b[0mval_acc\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mhistory\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mhistory\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'val_acc'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      3\u001b[0m \u001b[0mloss\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mhistory\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mhistory\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'loss'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      4\u001b[0m \u001b[0mval_loss\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mhistory\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mhistory\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'val_loss'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      5\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mNameError\u001b[0m: name 'history' is not defined"
     ]
    }
   ],
   "source": [
    "acc = history.history['acc']\n",
    "val_acc = history.history['val_acc']\n",
    "loss = history.history['loss']\n",
    "val_loss = history.history['val_loss']\n",
    "\n",
    "epochs = range(1, len(acc) + 1)\n",
    "\n",
    "plt.plot(epochs, acc, 'bo', label='Training Acc')\n",
    "plt.plot(epochs, val_acc, 'b', label='Validation Acc')\n",
    "plt.title('Training and Validation Accuracy')\n",
    "plt.legend()\n",
    "\n",
    "plt.figure()\n",
    "\n",
    "plt.plot(epochs, loss, 'bo', label='Training loss')\n",
    "plt.plot(epochs, val_loss, ' b', label='Validation loss')\n",
    "plt.title('Training and Validation Accuracy')\n",
    "plt.legend()\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 使曲线平滑化"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'epochs' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-5-8a0291d61f66>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m     10\u001b[0m     \u001b[0;32mreturn\u001b[0m \u001b[0msmoothed_points\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     11\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 12\u001b[0;31m \u001b[0mplt\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mplot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mepochs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0msmooth_curve\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0macc\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'bo'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlabel\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'Smoothed training acc'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     13\u001b[0m \u001b[0mplt\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mplot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mepochs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0msmooth_curve\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mval_acc\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'b'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlabel\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'Smoothed validation acc'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     14\u001b[0m \u001b[0mplt\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlegend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mNameError\u001b[0m: name 'epochs' is not defined"
     ]
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "def smooth_curve(points, factor=0.8):\n",
    "    smoothed_points = []\n",
    "    for point in points:\n",
    "        if smoothed_points:\n",
    "            previous = smoothed_points[-1]\n",
    "            smoothed_points.append(previous * factor + point * (1- factor))\n",
    "        else:\n",
    "            smoothed_points.append(point)\n",
    "    return smoothed_points\n",
    "\n",
    "plt.plot(epochs, smooth_curve(acc), 'bo', label='Smoothed training acc')\n",
    "plt.plot(epochs, smooth_curve(val_acc), 'b', label='Smoothed validation acc')\n",
    "plt.legend()\n",
    "\n",
    "plt.figure()\n",
    "\n",
    "plt.plot(epochs, smooth_curve(loss), 'bo', label='Smoothed train loss')\n",
    "plt.plot(epochs, smooth_curve(val_loss), 'b', label='Smoothed validation loss')\n",
    "plt.legend()\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
